#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2020/10/26 14:51
# @Author  : Crissu
# @Site    : 
# @File    : drawPic.py
# @Software: PyCharm
'''
参考博客：
    excel读取: https://blog.csdn.net/u013250071/article/details/81911434
'''
import xlrd
import xlwt
from xlutils.copy import copy
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib

from ResultProcessing.configs import universalConfig

'''
    画图
'''
def drawPic(saveName, title, data):
    '''
    :param saveName: 图片保存名字
    :param title: 图片标题
    :param data: map, key:分类；value:精确度
    :return: None
    '''
    x = list()
    y = list()
    Y = list()
    num = 0
    # for item in data:
    #     x.append(item)
    #     Y.append(data[item])
    #     y.append(num)
    #     num += 1
    # #  增加一个功能，计算28种相似种平均识别率

    # class_similar28 = ['1tu_si_zi', '5nan_fang_tu_si_zi', '26dai_huang_feng',
    #                    '28ban_yuan_dou_fen_die', '30hei_wei_ao_da_ye_chan',
    #                    '32lv_zhong_si', '34zhang_wei_she_feng_die', '40dong_ya_fei_huang',
    #                    '41hu_po_dou_fen_die', '42hei_dai_shi_ya_ying',
    #                    '43bi_feng_die', '46ban_feng_die', '47zhong_hua_cao_zhong',
    #                    '48sui_ban_qing_feng_die', '57ri_ben_tiao_zhong_si',
    #                    '61xiao_hong_jia_die', '81hei_wei_ye_chan', '85mei_yan_jia_die',
    #                    '91da_hong_jia_die', '94duan_ban_you_cao_zhong',
    #                    '109kong_zi_qian_qiao_jia', '116hei_mai_jia_die',
    #                    '123mian_huang', '146xing_tian_niu', '152she_feng_die',
    #                    '168yu_feng_e', '171guang_jian_xing_tian_niu',
    #                    '172bian_qiao_jia']
    ## 这里改成26类
    class_similar26 = ['26dai_huang_feng',
                       '28ban_yuan_dou_fen_die', '30hei_wei_ao_da_ye_chan',
                       '32lv_zhong_si', '34zhang_wei_she_feng_die', '40dong_ya_fei_huang',
                       '41hu_po_dou_fen_die', '42hei_dai_shi_ya_ying',
                       '43bi_feng_die', '46ban_feng_die', '47zhong_hua_cao_zhong',
                       '48sui_ban_qing_feng_die', '57ri_ben_tiao_zhong_si',
                       '61xiao_hong_jia_die', '81hei_wei_ye_chan', '85mei_yan_jia_die',
                       '91da_hong_jia_die', '94duan_ban_you_cao_zhong',
                       '109kong_zi_qian_qiao_jia', '116hei_mai_jia_die',
                       '123mian_huang', '146xing_tian_niu', '152she_feng_die',
                       '168yu_feng_e', '171guang_jian_xing_tian_niu',
                       '172bian_qiao_jia']

    class_similar29 = ["128guang_lu_e", "19lei_lu_e", "32lv_zhong_si", "47zhong_hua_cao_zhong",
                       "57ri_ben_tiao_zhong_si", "94duan_ban_you_cao_zhong", "123mian_huang",
                       "40dong_ya_fei_huang", "64hong_he_ban_tui_huang", "28ban_yuan_dou_fen_die",
                       "41hu_po_dou_fen_die", "46ban_feng_die", "48sui_ban_qing_feng_die",
                       "168yu_feng_e", "61xiao_hong_jia_die", "85mei_yan_jia_die", "91da_hong_jia_die",
                       "116hei_mai_jia_die", "109kong_zi_qian_qiao_jia", "172bian_qiao_jia",
                       "146xing_tian_niu", "171guang_jian_xing_tian_niu", "30hei_wei_ao_da_ye_chan",
                       "81hei_wei_ye_chan", "26dai_huang_feng", "42hei_dai_shi_ya_ying",
                       "34zhang_wei_she_feng_die", "43bi_feng_die", "152she_feng_die"]

    extra = ['28ban_yuan_dou_fen_die', '34zhang_wei_she_feng_die', '43bi_feng_die',
             '128guang_lu_e', '19lei_lu_e', '109kong_zi_qian_qiao_jia', '172bian_qiao_jia',
             '146xing_tian_niu', '171guang_jian_xing_tian_niu', '104huang_xing_tian_niu',
             '163sang_tian_niu', '47zhong_hua_cao_zhong', '57ri_ben_tiao_zhong_si',
             '40dong_ya_fei_huang', '64hong_he_ban_tui_huang', '17gui_zhen_cao',
             '161ku_qiu_luo_wen_e']

    class_similar15 = ['46ban_feng_die', '48sui_ban_qing_feng_die', '116hei_mai_jia_die',
                       '61xiao_hong_jia_die', '85mei_yan_jia_die', '91da_hong_jia_die',
                       '168yu_feng_e', '152she_feng_die', '26dai_huang_feng',
                       '42hei_dai_shi_ya_ying', '30hei_wei_ao_da_ye_chan',
                       '81hei_wei_ye_chan', '32lv_zhong_si', '94duan_ban_you_cao_zhong',
                       '123mian_huang']

    class_65_id = [58,60,5,69,79,81,25,20,39,54,43,77,45,82,8,4,44,62,65,13,67,14,72,21,19,61,80,68,64,76,51,29,63,46,50,35,70,16,49,56,0,57,48,12,9,74,6,73,78,75,1,33,7,18,37,38,36,34,31,15,11,22,26,40,42]
    class_65_name = ['46ban_feng_die', '48sui_ban_qing_feng_die', '116hei_mai_jia_die', '61xiao_hong_jia_die', '85mei_yan_jia_die', '91da_hong_jia_die', '168yu_feng_e', '152she_feng_die', '26dai_huang_feng', '42hei_dai_shi_ya_ying', '30hei_wei_ao_da_ye_chan', '81hei_wei_ye_chan', '32lv_zhong_si', '94duan_ban_you_cao_zhong', '123mian_huang', '112bai_nong_die', '31ya_hui_die', '50lao_bao_jia_die', '55zhong_huan_jia_die', '137qu_wen_zhi_jia_die', '59si_dai_feng_die', '139yu_dai_feng_die', '70jin_shang_feng_die', '158chong_yang_mu_jin_ban_e', '150qing_feng_die', '49liu_li_jia_die', '87hei_nong_die', '60cui_lan_yan_jia_die', '54bai_dai_ao_jia_die', '79dao_mei_yan_die', '39zhi_wen_dao_nong_die', '178wu_jiu_da_can_e', '51gan_shu_la_gui_jia', '33lv_hui_die', '38an_mai_cai_fen_die', '21juan_fen_die', '63liu_li_hui_die', '141mei_guo_bai_e', '36ka_fei_tou_chi_tian_e', '44qing_bei_zhang_hui_tian_e', '100zhu_ma_shuang_ji_tian_niu', '45pu_tong_lou_gu', '35zi_jing_jia', '134zhong_hua_xi_shuai', '126hei_e_guang_ye_jia', '74shi_xing_piao_ying_ye_jia', '119dou_yan_jing', '71zhang_jian_ji_yuan_chun', '83hong_ji_zhang_chun', '77tou_ming_shu_guang_la_chan', '101huang_yang_juan_ye_ming', '1tu_si_zi', '11yang_ti', '14lv_cao', '24ping_che_qian', '25tun_cao', '22nie_li', '20bai_mao', '18sang_ji_sheng', '13luo_shi', '12xi_han_lian_zi_cao', '15ye_ge', '16wu_zhao_jin_long', '27feng_yan_lian', '2niu_qie_zi']

    className_74 = ['46ban_feng_die', '48sui_ban_qing_feng_die', '116hei_mai_jia_die', '61xiao_hong_jia_die',
                    '85mei_yan_jia_die', '91da_hong_jia_die', '168yu_feng_e', '152she_feng_die', '26dai_huang_feng',
                    '42hei_dai_shi_ya_ying', '30hei_wei_ao_da_ye_chan', '81hei_wei_ye_chan', '32lv_zhong_si',
                    '94duan_ban_you_cao_zhong', '123mian_huang', '109kong_zi_qian_qiao_jia', '172bian_qiao_jia',
                    '146xing_tian_niu', '171guang_jian_xing_tian_niu', '104huang_xing_tian_niu', '163sang_tian_niu',
                    '47zhong_hua_cao_zhong', '57ri_ben_tiao_zhong_si', '40dong_ya_fei_huang', '112bai_nong_die',
                    '31ya_hui_die', '50lao_bao_jia_die', '55zhong_huan_jia_die', '137qu_wen_zhi_jia_die',
                    '59si_dai_feng_die', '139yu_dai_feng_die', '70jin_shang_feng_die', '158chong_yang_mu_jin_ban_e',
                    '150qing_feng_die', '49liu_li_jia_die', '87hei_nong_die', '60cui_lan_yan_jia_die',
                    '54bai_dai_ao_jia_die', '79dao_mei_yan_die', '39zhi_wen_dao_nong_die', '178wu_jiu_da_can_e',
                    '51gan_shu_la_gui_jia', '33lv_hui_die', '38an_mai_cai_fen_die', '21juan_fen_die',
                    '63liu_li_hui_die', '141mei_guo_bai_e', '36ka_fei_tou_chi_tian_e', '44qing_bei_zhang_hui_tian_e',
                    '100zhu_ma_shuang_ji_tian_niu', '45pu_tong_lou_gu', '35zi_jing_jia', '134zhong_hua_xi_shuai',
                    '126hei_e_guang_ye_jia', '74shi_xing_piao_ying_ye_jia', '119dou_yan_jing',
                    '71zhang_jian_ji_yuan_chun', '83hong_ji_zhang_chun', '77tou_ming_shu_guang_la_chan',
                    '101huang_yang_juan_ye_ming', '1tu_si_zi', '11yang_ti', '14lv_cao', '24ping_che_qian', '25tun_cao',
                    '22nie_li', '20bai_mao', '18sang_ji_sheng', '13luo_shi', '12xi_han_lian_zi_cao', '15ye_ge',
                    '16wu_zhao_jin_long', '27feng_yan_lian', '2niu_qie_zi']

    averageAccuracy = 0
    averageAccuracy_26 = 0
    similarClassesMap_26 = {}
    similarClassesIdxMap_26 = []

    averageAccuracy_29 = 0
    similarClassesMap_29 = {}
    similarClassesIdxMap_29 = []

    averageAccuracy_74 = 0
    similarClassesMap_74 = {}
    similarClassesIdxMap_74 = []

    averageAccuracy_15 = 0
    averageAccuracy_65 = 0
    nn = 0
    for i in range(85):
        if universalConfig.idx2classMap[i] in class_65_name:
            averageAccuracy_65 += data[i]
            nn += 1
        if universalConfig.idx2classMap[i] in class_similar15:
            averageAccuracy_15 += data[i]
    print(nn)
    print('averageAccuracy_15:', averageAccuracy_15/15)
    print('averageAccuracy_65:', averageAccuracy_65/65)


    for i in range(85):
        x.append(i)
        averageAccuracy += data[i]
        Y.append(data[i])
        y.append(i)
        num += 1
        if universalConfig.idx2classMap[i] in class_similar26:
            similarClassesIdxMap_26.append(i)
            similarClassesMap_26[universalConfig.idx2classMap[i]] = round(data[i], 2)
            averageAccuracy_26 += data[i]

        if universalConfig.idx2classMap[i] in class_similar29:
            similarClassesIdxMap_29.append(i)
            similarClassesMap_29[universalConfig.idx2classMap[i]] = round(data[i], 2)
            averageAccuracy_29 += data[i]

        if universalConfig.idx2classMap[i] in className_74:
            similarClassesIdxMap_74.append(i)
            similarClassesMap_74[universalConfig.idx2classMap[i]] = round(data[i], 2)
            averageAccuracy_74 += data[i]

    averageAccuracy = averageAccuracy / 85
    averageAccuracy_26 = averageAccuracy_26 / 26
    averageAccuracy_29 = averageAccuracy_29 / 29
    averageAccuracy_74 = averageAccuracy_74 / 74
    print("averageAccuracy: ", averageAccuracy)
    print("averageAccuracy_26:", averageAccuracy_26)
    print("similarClassesMap_26:", similarClassesMap_26)
    print("similarClassesIdxMap_26:", similarClassesIdxMap_26)
    print("averageAccuracy_29:", averageAccuracy_29)
    print("similarClassesMap_29:", similarClassesMap_29)
    print("similarClassesIdxMap_29:", similarClassesIdxMap_29)
    print("averageAccuracy_74:", averageAccuracy_74)
    print(Y)
    fig = plt.figure()
    songTi = matplotlib.font_manager.FontProperties(fname='C:\Windows\Fonts\simsun.ttc')
    plt.bar(x, Y, 0.4, color="green")
    plt.xlabel("类别", fontproperties=songTi, fontsize=14)
    plt.xticks(y, fontsize=3)
    plt.ylabel("精确度", fontproperties=songTi, fontsize=14)
    plt.title(title, fontproperties=songTi, fontsize=16)
    plt.savefig(saveName, dpi=1000)
    plt.show()

'''
    读取模型测试生成的test.xls结果
'''
def readTestXls(path):
    '''
    :param path: .xls文件路径
    :return: accuracyMap, key:idx value:accuracy
    '''
    workbook = xlrd.open_workbook(path)  # 打开工作簿
    sheets = workbook.sheet_names()  # 获取工作簿中的所有表格
    worksheet = workbook.sheet_by_name(sheets[0])  # 获取工作簿中所有表格中的的第一个表格
    correctMap = {}  # key:分类；value:正确个数
    accuracyMap = {}  # key:分类；value:精确度
    numsMap = {}  # # key:idx下标；value:该类总个数
    for i in range(85):
        correctMap[i] = 0
        numsMap[i] = 0

    # 计算正确个数和分类总个数
    for i in range(1, worksheet.nrows):
        groundTruth = int(worksheet.cell_value(i, 1))
        predict = int(worksheet.cell_value(i, 2))
        # 正确个数
        if groundTruth == predict:
            if groundTruth not in correctMap:
                correctMap[groundTruth] = 1
            correctMap[groundTruth] += 1
        # 每一类总数计数
        if groundTruth not in numsMap:
            numsMap[groundTruth] = 1
        numsMap[groundTruth] += 1
    # 计算每一类精确度
    small90 = list()
    small80 = list()
    small60 = list()
    small30 = list()

    for item in correctMap:
        if item not in accuracyMap:
            ave = (correctMap[item] / numsMap[item]) * 100
            accuracyMap[item] = ave
            if ave <= 90:
                small90.append(item)
            if ave <= 80:
                small80.append(item)
            if ave <= 60:
                small60.append(item)
            if ave <= 30:
                small30.append(item)
    cla90 = list()
    for item in small90:
        cla90.append(universalConfig.idx2classMap[item])
    cla80 = list()
    for item in small80:
        cla80.append(universalConfig.idx2classMap[item])
    cla60 = list()
    for item in small60:
        cla60.append(universalConfig.idx2classMap[item])
    cla30 = list()
    for item in small30:
        cla30.append(universalConfig.idx2classMap[item])
    print("低于90的类, 数量：", len(cla80))
    print(cla90)
    print("低于80的类, 数量：", len(cla80))
    print(cla80)
    print("低于60的类, 数量：", len(cla60))
    print(cla60)
    print("低于30的类, 数量：", len(cla30))
    print(cla30)

    print("accuracyMap[27]:", accuracyMap[27])
    return accuracyMap


# 把结果写入到excel
def WriteExcel(path, idxs, zh_names, yw_names, accuracys):
    # 创建一个Workbook对象，相当于创建了一个Excel文件
    book = xlwt.Workbook(encoding="utf-8", style_compression=0)
    # 创建一个sheet对象，一个sheet对象对应Excel文件中的一张表格。
    sheet = book.add_sheet('result', cell_overwrite_ok=True)
    # 设置表头
    tableHead = ['idx', 'zh_names', 'yw_names', 'accuracy']
    for i in range(len(tableHead)):
        sheet.write(0, i, tableHead[i])
    for i in range(len(idxs)):
        # 写入idx
        sheet.write(i+1, 0, idxs[i])
        # 写入中文名
        sheet.write(i+1, 1, zh_names[i])
        # 写入拼音名
        sheet.write(i + 1, 2, yw_names[i])
        # 写入识别率
        sheet.write(i + 1, 3, accuracys[i])
    # 保存
    book.save(path)

'''
    画精确度图
'''
def drawAccuracyPic():
    '''
    :return: None
    '''
    book_name_xls = 'dbt-resnext50_result_gt.xls'  # .xls文件名字
    # 读取表格
    accuracyMap = readTestXls(book_name_xls)
    print("accuracyMap:")
    print(accuracyMap)

    #################
    #   结果分析
    #################
    idxs = list()
    zh_names = list()
    yw_names = list()
    accuracys = list()
    for idx in accuracyMap:
        idxs.append(str(idx))
        zh_names.append(universalConfig.ywName2zhNameMap[universalConfig.idx2classMap[idx]])
        yw_names.append(universalConfig.idx2classMap[idx])
        accuracys.append(accuracyMap[idx])
    # 写入表格保存
    WriteExcel("./idx_zhName_ywName.xls", idxs, zh_names, yw_names, accuracys)




    #################

    # 画图
    title = "85类林业有害生物精确度结果"
    saveName = book_name_xls[:len(book_name_xls)-4]+"_85类林业有害生物精确度结果.jpg"
    drawPic(saveName, title, accuracyMap)


if __name__ == '__main__':
    # 画精确度图
    drawAccuracyPic()
